# (C) 2019, Chen Xiao <chen_xiao@bosc.cn>
# (C) 2019, Internal Use

from __future__ import (absolute_import, division, print_function)

__metaclass__ = type

import time
import os
import json
from ansible.plugins.callback import CallbackBase

DOCUMENTATION = '''
    callback: jsonfile_facts
    type: notification
    requirements:
        - whitelist in configuration
    short_description: proceed facts stdout to json file
    description:
        - get base facts with module setup
        - get extra facts with module linux_facts or hpux_facts.
'''


CACHE_EXTRA_FACTS_PATH = os.environ.get('CACHE_EXTRA_FACTS_PATH')
CACHE_BASE_FACTS_PATH = os.environ.get('CASHE_BASE_FACTS_PATH')
suffix = '.json'


class CallbackModule(CallbackBase):
    CALLBACK_VERSION = 2.0
    CALLBACK_TYPE = 'notification'
    CALLBACK_NAME = 'jsonfile_extra_facts'
    CALLBACK_NEEDS_WHITELIST = True

    def __init__(self):
        super(CallbackModule, self).__init__()
        self.check_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        self.task_tags = ['jsonfile_base_facts', 'jsonfile_extra_facts']
        self.task_actions = ['debug']

        if not CACHE_BASE_FACTS_PATH:
            self.cache_base_facts_path = '/tmp/cache_base_facts'
        else:
            self.cache_base_facts_path = CACHE_BASE_FACTS_PATH
        if not os.path.exists(self.cache_base_facts_path):
            os.makedirs(self.cache_base_facts_path)

        if not CACHE_EXTRA_FACTS_PATH:
            self.cache_extra_facts_path = '/tmp/cache_extra_facts'
        else:
            self.cache_extra_facts_path = CACHE_EXTRA_FACTS_PATH

        if not os.path.exists(self.cache_extra_facts_path):
            os.makedirs(self.cache_extra_facts_path)

    def write(self, facts_type, ip, data):
        if facts_type == 'extra':
            path = self.cache_extra_facts_path
        elif facts_type == 'base':
            path = self.cache_base_facts_path

        jsonfile = os.path.join(path, ip)
        if os.path.exists(jsonfile+suffix):
            os.remove(jsonfile+suffix)

        with open(jsonfile, "wb+") as f:
            json.dump(data, f, indent=True)

    def load(self, result):
        host = result._host.get_name()
        hostvar = self.play._variable_manager._hostvars.get(host)
        # hostname = hostvar.get('ansible_hostname', '')
        # item = result.task_name
        # rc = result._result.get('rc', -1)
        # stderr = result._result.get('stderr', -1)
        # stdout = result._result.get('stdout', -1)
        # check_tag = hostvar.get('checktag', '')
        if hostvar.get('ansible_system') == 'Linux':
            ip = hostvar.get('ansible_default_ipv4', {}).get('address', host)
        elif hostvar.get('ansible_system') == 'Win32NT':
            ip = hostvar.get('ansible_ip_addresses', [host])[0]
        else:
            ip = host

        unreachable = result._result.get('unreachable', 'false')
        failed = result._result.get('failed', 'false')

        line = {}
        facts_type = 'base'
        line['unreachable'] = unreachable
        line['failed'] = failed

        if 'jsonfile_base_facts' in result._task.tags:
            base_facts = result._result.get('base_facts', {})
            line['base_facts'] = base_facts
            facts_type = 'base'
        elif 'jsonfile_extra_facts' in result._task.tags:
            extra_facts = result._result.get('extra_facts', {})
            line['extra_facts'] = extra_facts
            self.write('extra', ip+suffix, line)
            facts_type = 'extra'

        self.write(facts_type, ip+suffix, line)
        # self._display.display('Results: "%s", "%s", "%s", "%s"' % (ip, result._task.tags, line))

    def v2_runner_on_failed(self, result, ignore_errors=False):
        if result._host.get_name() != 'localhost':
            result._result['failed'] = "true"
            self.load(result)

    def v2_runner_on_ok(self, result):
        self._display.display('Results: "%s", "%s"' % (self.task_tags, result._task.tags))
        for task_tag in self.task_tags:
            if task_tag in result._task.tags and result._task.action in self.task_actions:
                self.load(result)

    def v2_runner_on_skipped(self, result):
        if result._host.get_name() != 'localhost':
            result._result['rc'] = -2
            result._result['stdout'] = 'Skipped: %s' % result._result.get('skip_reason')
            self.load(result)

    def v2_runner_on_unreachable(self, result):
        if result._host.get_name() != 'localhost':
            result._result['unreachable'] = 'true'
            self.load(result)

    def v2_playbook_on_play_start(self, play):
        self.play = play
